package org.example.com.processor;

import org.example.com.annotation.MRPAnnotations;
import org.example.com.entity.BillOfMaterials;
import org.example.com.entity.Inventory;
import org.example.com.entity.Item;
import org.example.com.entity.MasterProductionSchedule;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * MRP计算模块
 */
@MRPAnnotations.MRPEntity("MRP计算引擎")
public class MRPProcessor {

    private List<BillOfMaterials> boms;
    private Inventory inventory;
    private Map<Item, Integer> netRequirements = new HashMap<>();

    public MRPProcessor(List<BillOfMaterials> boms, Inventory inventory) {
        this.boms = boms;
        this.inventory = inventory;
    }

    // 开始MRP运算
    public Map<Item, Integer> runMRP(MasterProductionSchedule mps) {
        netRequirements.clear();

        //最终产品及其需求数量遍历
        for (Map.Entry<Item, Integer> entry : mps.getProductionPlan().entrySet()) {
            //获取最终需求产品名
            Item root = entry.getKey();
            //获取最终需求产品数量
            int quantity = entry.getValue();
            explode(root, quantity);
        }
        //根据进货策略进货
        return netRequirements;
    }

    // 递归展开BOM
    //根据最终需求产品名和最终需求产品数量运算
    //从产品开始，逐步向下级物料推算，逐级计算产品和各级物料需求数量
    private void explode(Item item, int requiredQty) {
        //库存中数量减去需求数量
        int available = inventory.getCurrentStock(item);
        int netNeed = requiredQty - available;

        //若库存中不够，将库存中所有存入列表
        if (netNeed > 0) {
            netRequirements.put(item, netNeed);
        }

        //若不是最终产品，则遍历物料清单
        for (BillOfMaterials bom : boms) {
            //物料的父Id和需求的Id相同(该物料是生产需求产品所需的物料)
            if (bom.getParent().getItemId().equals(item.getItemId())) {
                for (Map.Entry<Item, Integer> component : bom.getComponents().entrySet()) {
                    //获取物料名
                    Item child = component.getKey();
                    //获取需要的物料数量
                    int qtyNeeded = component.getValue() * netNeed;
                    explode(child, qtyNeeded);
                }
            }
        }
    }

    //调整进货策略
    public Map<Item, Integer> generatePurchaseOrders(Map<Item, Integer> netRequirements) {
        Map<Item, Integer> purchaseOrders = new HashMap<>();

        //复制netRequirements，避免影响其他地方计算
        HashMap<Item, Integer> netRequirementsPurchaseOrders = new HashMap<>();
        netRequirementsPurchaseOrders.putAll(netRequirements);

        // 遍历 netRequirementsPurchaseOrders，根据批量策略调整订购数量
        Iterator<Map.Entry<Item, Integer>> iterator = netRequirementsPurchaseOrders.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Item, Integer> entry = iterator.next();
            Item item = entry.getKey();
            int netNeed = entry.getValue();

            // 跳过最终产品，并从 netRequirements 中移除
            if (item.isFinishedGood()) {
                iterator.remove(); // 安全删除
                continue;
            }

            // 根据批量策略调整订购数量
            int orderQuantity = adjustOrderQuantity(item, netNeed);

            if (orderQuantity > 0) {
                purchaseOrders.put(item, orderQuantity);
                // 检查是否达到再订货点并提醒进货
                checkAndAlertReorder(item);
            }
        }

        return purchaseOrders;
    }


    //MRP进货规则计算
    private int adjustOrderQuantity(Item item, int netNeed) {
        if (item.getLotSizeStrategy() != null && item.isFinishedGood() != true){
            switch (item.getLotSizeStrategy()) {
                case FIXED_LOT_SIZE:
                    // 固定批量大小
                    return roundUpToMultiple(netNeed, item.getFixedLotSize());
                case MULTIPLE_OF_FIXED:
                    // 按某个固定数的倍数订货
                    return roundUpToMultiple(netNeed,item.getMultipleOfFixed());
                case ECONOMIC_ORDER_QUANTITY:
                    int eoq = item.calculateEoq();
                    if (netNeed <= eoq){
                        return eoq;
                    }
                    return roundUpToMultiple(netNeed, eoq);
                default:
                    return netNeed; // 默认按净需求数量订货
            }
        }
        return netNeed;
    }

    /**
     * 将数值 value 向上取整为 multiple 的最小整数倍
     */
    private int roundUpToMultiple(int value, int multiple) {
        if (multiple == 0) return value;
        return ((value + multiple - 1) / multiple) * multiple;
    }

    /**
     * 检查物料的当前库存是否低于再订货点，并提醒进货
     */
    private void checkAndAlertReorder(Item item) {
        int currentStock = inventory.getCurrentStock(item);
        int reorderPoint = item.calculateReorderPoint();
        if (currentStock < reorderPoint) {
            System.out.println("警告: 物料 " + item.getItemName() + " 当前库存为 " + currentStock + " 已低于再订货点 " + reorderPoint + "，建议立即补货！");
        }
    }
}